﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace SpectrEngine.Framework.Collision
{
    public sealed class CollisionManager
    {
        private Game game;
        public Game Game
        {
            get { return game; }
        }

        private List<CollidableGameNode> nodesToCollide;
        private QuadTree quadTree;
        private HashSet<CollisionItem> collisions;

        public CollisionManager(Game game, BoundingRect worldBounds, int maxNodes)
        {
            this.game = game;
            nodesToCollide = new List<CollidableGameNode>();
            collisions = new HashSet<CollisionItem>();

            quadTree = new QuadTree(worldBounds, maxNodes);
        }

        #region Collision

        public void GenerateCollisions()
        {
            collisions.Clear();

            foreach (CollidableGameNode node in nodesToCollide)
            {
                node.Collided = false;
            }

            List<CollidableGameNode> results = new List<CollidableGameNode>();

            foreach (CollidableGameNode leftNode in nodesToCollide)
            {
       
                quadTree.GetNodes(leftNode.Bounds, ref results);

                foreach (CollidableGameNode rightNode in results)
                {
                    if (leftNode == rightNode)
                    {
                        continue;
                    }
                    if (zoneCollision(leftNode, rightNode))
                    {
                        collisions.Add(new CollisionItem(leftNode, rightNode));
                        rightNode.Collided = true;
                    }
                }

                results.Clear();
            }
        }

        public void ProcessCollisions()
        {
            foreach (CollisionItem collision in collisions)
            {
                collision.First.CollideWith(collision.Second);
                collision.Second.CollideWith(collision.First);
            }
        }

        private bool zoneCollision(CollidableGameNode first, CollidableGameNode second)
        {
            for(int i = 0; i < first.AttackZones.Count(); i++)
            {
                BoundingCircle left = new BoundingCircle(first.AttackZones[i], first.World);

                for (int j = 0; j < second.AttackZones.Count(); j++)
                {
                    BoundingCircle right = new BoundingCircle(second.AttackZones[j], second.World);
                    if (left.Intersects(right))
                    {
                        return true;
                    }
                }
            }

            return false;
        }

        #endregion

        #region Register

        public void Register(CollidableGameNode node)
        {
            node.Disposed += new EventHandler(node_Disposed);
            quadTree.Add(node);
            nodesToCollide.Add(node);
        }

        void node_Disposed(object sender, EventArgs e)
        {
            nodesToCollide.Remove((CollidableGameNode)sender);
        }

        #endregion


    }
}
